const mapArray = require('map-array');
var mapObject = require('map-obj');

const obj = {FOO: true, bAr: {bAz: true}} ;


var newObject = mapObject( 
   obj,
  (key, value) => [key.toLowerCase(), value], {deep: true}
);

console.log(newObject, newObject === obj, obj)
console.log('-------------------------------------\n')



var newObject = myMapObject( 
   obj,
  (key, value) => [key.toLowerCase(), value], {deep: true}
);
console.log(newObject)

/**
 * 根据mapper进行遍历对象
 * @param  {[type]} object  [description]
 * @param  {[type]} mapper  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
function myMapObject(object, mapper, options) {
	function isObject (x) { 
		return typeof x === 'object' &&
			x !== null &&
			!(x instanceof RegExp) &&
			!(x instanceof Error) &&
			!(x instanceof Date); 
	}

	// 内部再定义一个函数处理主要的工作
	const mapObject = (object, mapper, options, isSeen = new WeakMap()) => {

		// deep 默认 false, target
		options = {
			deep: false,
			target: {},
			...options
		};

		// 防止循环引用
		if (isSeen.has(object)) {
			return isSeen.get(object);
		}
		isSeen.set(object, options.target);

		const {target} = options;
		delete options.target;

		// mapArray也是定义的一个函数， 用来遍历数组
		const mapArray = array => array.map(element => isObjectCustom(element) ? 
				mapObject(element, mapper, options, isSeen) : element);

		if (Array.isArray(object)) {
			return mapArray(object);
		}

		// 遍历对象
		for (const [key, value] of Object.entries(object)) {
			// mapper外面调用者传递过来的一个回调, 这里传入了3个参数(key, value, object)
			let [newKey, newValue] = mapper(key, value, object);

			// 判断是否要进行递归操作 
			if(options.deep && isObject(newValue)) {
				// 是否是数组还是对象
				newValue =  Array.isArray(newValue) ?
				mapArray(newValue) :
				mapObject(newValue, mapper, options, isSeen);
			}	

			target[newKey] = newValue
		}

		
		return target;
	}

	return mapObject(object, mapper, options);
}